//    Copyright (C) Kherty.  All rights reserved.
using System;

namespace OpenLS.Spreadsheet.StandardAddIn.Statistics
{
    internal class NormalDistribution : ContinuousDistribution
    {
        private double _mean = 0;
        private double _standardDeviation = 1;

        public NormalDistribution(double mean, double sd)
        {
            Mean = mean;
            StandardDeviation = sd;
        }

        public NormalDistribution()
            : this(0.0, 1.0)
        {
        }

        public double Mean
        {
            get { return _mean; }
            set { _mean = value; }
        }

        public double StandardDeviation
        {
            get { return _standardDeviation; }
            set
            {
                if (value <= 0.0)
                    throw new ArgumentOutOfRangeException("value");
                _standardDeviation = value;
            }
        }

        public override double CumulativeProbability(double x)
        {
            return 0.5*(1.0 + Statistician.ErrorFunction((x - _mean)/(_standardDeviation*Math.Sqrt(2.0))));
        }

        public override double InverseCumulativeProbability(double p)
        {
            if (p == 0)
                return double.NegativeInfinity;
            if (p == 1)
                return double.PositiveInfinity;
            return base.InverseCumulativeProbability(p);
        }

        protected override SolverParameters GetSolverParameters(double probability)
        {
            return new SolverParameters(
                probability < 0.5 ? -double.MaxValue : Mean,
                probability < 0.5 ? Mean : double.MaxValue,
                probability < 0.5 ? Mean - StandardDeviation : (probability > 0.5 ? Mean + StandardDeviation : Mean));
        }

        public double Probability(double X)
        {
            double SQRT2PI = Math.Sqrt(2*Math.PI);
            double pdfDenominator = SQRT2PI*StandardDeviation;
            double variance = StandardDeviation*StandardDeviation;
            return Math.Exp(-(X - Mean)*(X - Mean)/(2*variance))/pdfDenominator;
        }
    }
}